package com.douqu.game.core.entity.world.map;

import com.bean.core.buffer.ByteBuffer;
import com.douqu.game.core.config.StableDataConfig;
import com.douqu.game.core.config.common.GoodsData;
import com.douqu.game.core.config.map.CityConfig;
import com.douqu.game.core.controller.PlayerController;
import com.douqu.game.core.e.E_ActionPlayerType;
import com.douqu.game.core.e.E_CityInOutType;
import com.douqu.game.core.e.E_StableDataType;
import com.douqu.game.core.entity.Player;
import com.douqu.game.core.entity.battle.BattleTemp;
import com.douqu.game.core.entity.ext.BagInfo;
import com.douqu.game.core.entity.ext.SettingInfo;
import com.douqu.game.core.factory.ConstantFactory;
import com.douqu.game.core.factory.DataFactory;
import com.douqu.game.core.factory.WorldInfoFactory;
import com.douqu.game.core.protobuf.SGCommonProto;
import com.douqu.game.core.util.LogUtils;
import com.douqu.game.core.util.SendUtils;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 行动对象
 *
 * @Author: Bean
 * @Description:
 * @Date: 2018-04-16 16:52
 */
public class SpritePlayerBean extends SpriteBean
{
    /**
     * 行动对象类型
     */
    private E_ActionPlayerType actionPlayerType;


    /**
     * 当前所在城市
     */
    private int curRouteIndex;

    /**
     * 路线(里面的值是城的ID)
     */
    private List<Integer> routeList;

    /**
     * 只有是玩家的时候才有这个对象
     */
    private PlayerController playerController;

    /**
     * 离线时设置Player对象
     */
    private Player player;

    /**
     * 恢复状态时的参数
     */
    private RecoverParam recoverParam;

    /**
     * 退出大地图时间
     */
    private long outMapTime;

    /**
     * 手动点快速匹配的时候把这个值设为true,保证匹配都只在一个线程里操作
     */
    private boolean manualMatch = false;

    /**
     * 手动挑战指定玩家
     */
    private String manualMatchPlayerIndex;

    public SpritePlayerBean(String masterPlayerIndex)
    {
        super();

        routeList = new CopyOnWriteArrayList<>();
        curRouteIndex = -1;
        this.masterPlayerIndex = masterPlayerIndex;
    }

    public SpritePlayerBean(E_ActionPlayerType type, Player player, int city, String masterPlayerIndex)
    {
        this(masterPlayerIndex);

        this.camp = player.camp;
        this.actionPlayerType = type;
        this.objectIndex = player.getObjectIndex();

        setCurCity(city);

		updateBaseInfo(player);
        initBattleTemp(player);
	}

    @Override
    public void loadFrom(ByteBuffer buffer)
    {
        super.loadFrom(buffer);

        baseInfo.setObjectIndex(objectIndex);
    }

    @Override
    public void writeTo(ByteBuffer buffer)
    {
        super.writeTo(buffer);
    }

    @Override
    public void update(WorldMapUpdateResult updateResult) {
        if (isRemove)
            return;

        if(actionPlayerType != E_ActionPlayerType.ONLINE_MAP)
        {
            if(status == SGCommonProto.E_ARMY_STATUS.ARMY_STATUS_MOVE && isOverdueStatus())
            {
                LogUtils.info("服务器自动行走开始 -> 玩家:" + objectIndex + " 当前城:" + getCurCity() + " 路线:" + routeList);
                autoMove();

                //客户端口告诉服务器要恢复才恢复，所以这里自动行走就不执行恢复了
//                if(isFree() && getCurCity() != 0 && WorldInfoFactory.getInstance().getWorldMapData().getCurCity(this).getConfig().canConscript)
//                {
//                    updateResult.addRecoverPlayer(this);
//                }
                LogUtils.info("服务器自动行走完成 -> 玩家:" + objectIndex + " 当前城:" + getCurCity() + " 路线:" + routeList);
            }
        }


    }


    public void checkRemove()
    {
        if(outMapTime > 0)
        {
            if(!isBattleOrPrepare() && !isMatch())
            {
                if(DataFactory.currentTime - outMapTime >= 600000)
                {
                    LogUtils.warn("玩家已经离开城超时了，现在将他删除 -> " + getName());
                    isRemove = true;
                    outMapTime = 0;
                }
            }
        }
    }

    @Override
    public void sendWarn(String key, Object... params)
    {
        if (isCanSendMsg())
            playerController.sendWarn(key, params);
    }


    @Override
    public void sendMsg(int code, byte[] data)
    {
        if (isCanSendMsg())
            playerController.sendMsg(code, data);
    }


    /**
     * 大地图中玩家移动
     * @param targetCity
     * @return
     */
    public int move(int targetCity)
    {
        if(routeList.isEmpty())
            return 0;

        if(curRouteIndex >= routeList.size()-1)
            return 0;

        if(targetCity != routeList.get(curRouteIndex+1))
            return 0;

        return updateMove(E_CityInOutType.OUT_DEFAULT_ARRIVE);
    }

    /**
     * 移动
     * @return 当前最新到达的城市，为0表示非法移动
     */
    public void autoMove()
    {
        if(routeList.isEmpty())
            return;

        if(isEndRoute())
            return;

        int curCityId = updateMove(E_CityInOutType.OUT_AUTO_MOVE);

        if(curCityId != 0)
        {
            CityBean cityBean = WorldInfoFactory.getInstance().getWorldMapData(masterPlayerIndex).getCity(curCityId);
            cityBean.arrive(this, false, E_CityInOutType.IN_AUTO_MOVE);
        }
    }

    private int updateMove(E_CityInOutType type)
    {
        leaveCurCity(type);

        curRouteIndex++;

        int curCity = routeList.get(curRouteIndex);
        LogUtils.debug("移动后当前的城 -> " + curCity);
        if (isEndRoute())
        {
            stop();
            setStatus(SGCommonProto.E_ARMY_STATUS.ARMY_STATUS_FREE);
        }
        else
        {
            setStatus(SGCommonProto.E_ARMY_STATUS.ARMY_STATUS_MOVE);
        }

        return curCity;
    }

    public void leaveCurCity(E_CityInOutType type)
    {
        WorldMapData worldMapData = WorldInfoFactory.getInstance().getWorldMapData(masterPlayerIndex);
        CityBean cityBean = worldMapData.getCurCity(this);
        if (cityBean != null) cityBean.leave(this, null, type);
        setInCity(false);
    }


    public void stop() {
        curRouteIndex = -1;
        routeList.clear();
    }

    public boolean isEndRoute() {
        return curRouteIndex >= routeList.size() - 1;
    }

    public void initRoute(List<Integer> routeList)
    {
        stop();

        if(routeList.isEmpty())
            return;

        this.routeList.addAll(routeList);
        if(routeList.get(0) != getCurCity())
            this.curRouteIndex = -1;
        else
            this.curRouteIndex = 0;
//        this.setCurCity(routeList.get(curRouteIndex));
//        this.curCity = routeList.get(curRouteIndex);
        this.setStatus(routeList.size() == 1 ? SGCommonProto.E_ARMY_STATUS.ARMY_STATUS_FREE : SGCommonProto.E_ARMY_STATUS.ARMY_STATUS_MOVE);
    }

    public void clearRoute()
    {
        curRouteIndex = -1;
        routeList.clear();
        setInCity(false);
    }


    public int getNextCity() {
        if (routeList.isEmpty())
            return 0;

        if (curRouteIndex >= routeList.size() - 1)
            return 0;

        return routeList.get(curRouteIndex + 1);
    }

    public int getStartCity()
    {
        if(routeList.isEmpty())
            return 0;

        return routeList.get(0);
    }

    @Override
    public void setStatus(SGCommonProto.E_ARMY_STATUS value)
    {
        SGCommonProto.E_ARMY_STATUS beforeStatus = this.status;

        super.setStatus(value);

        if(status != SGCommonProto.E_ARMY_STATUS.ARMY_STATUS_RECOVER)
            setRecoverParam(null);

        if(beforeStatus != this.status && playerController != null && actionPlayerType == E_ActionPlayerType.ONLINE_MAP)
        {
            SendUtils.sendMapArmyStatus(playerController, this.status);
        }

        if(beforeStatus == SGCommonProto.E_ARMY_STATUS.ARMY_STATUS_RECOVER && status != SGCommonProto.E_ARMY_STATUS.ARMY_STATUS_RECOVER)
        {
            checkInitCard();

            if(playerController != null)
                SendUtils.sendWorldMapHPUpdate(playerController);
        }

        if(beforeStatus != SGCommonProto.E_ARMY_STATUS.ARMY_STATUS_RECOVER && status == SGCommonProto.E_ARMY_STATUS.ARMY_STATUS_RECOVER)
        {
            if(playerController != null)
                SendUtils.sendWorldMapHPUpdate(playerController, 10);
        }
    }

    /**
     * 检测是否在重新初始化卡组
     */
    public void checkInitCard()
    {
        if(playerController != null)
        {
            CityConfig cityConfig = DataFactory.getInstance().getGameObject(DataFactory.CITY_KEY, getCurCity());
            if(cityConfig != null && cityConfig.type == SGCommonProto.E_CITY_TYPE.CITY_TYPE_CAPITAL_VALUE && battleTemp.isFull())
            {
                //在主城，并且是恢复状态，并且是满血，重新初始化卡组
                playerController.getPlayer().getWorldMapTaskData().setBattleCardList(playerController.getPlayer().getCardData().getBattleCardList());
                updateBattleTemp(new BattleTemp(playerController.getPlayer(), 1, 1));
            }
        }
        else if(player != null)
        {
            CityConfig cityConfig = DataFactory.getInstance().getGameObject(DataFactory.CITY_KEY, getCurCity());
            if(cityConfig != null && cityConfig.type == SGCommonProto.E_CITY_TYPE.CITY_TYPE_CAPITAL_VALUE && battleTemp.isFull())
            {
                //在主城，并且是恢复状态，并且是满血，重新初始化卡组
                player.getWorldMapTaskData().setBattleCardList(player.getCardData().getBattleCardList());
                updateBattleTemp(new BattleTemp(player, 1, 1));
            }
        }
    }
    /**
     * 单次恢复
     */
    public void onceRecover()
    {
        if(recoverParam != null)
        {
            recoverParam.onceRecover(battleTemp);

//            if(recoverParam.getCount() <= 0 && playerController != null)
//            {
//                SendUtils.sendWorldMapHPUpdate(playerController);
//            }
        }
    }


    public void updatePlayer(Player player)
    {
        this.player = player;
        updateBaseInfo(player);
        initBattleTemp(player);
    }


    public void updateBaseInfo(Player player)
    {
		baseInfo.update(player);
    }

    public boolean isCanSendMsg()
    {
        return playerController != null && actionPlayerType == E_ActionPlayerType.ONLINE_MAP;
    }

    /**
     * 初始化战斗数据
     * @param player
     */
    public void initBattleTemp(Player player)
    {
        if(battleTemp == null)
        {
            battleTemp = new BattleTemp(player, 1, 1);
        }
    }



    public void setPlayerController(PlayerController playerController)
    {
        this.playerController = playerController;
        if(playerController != null)
        {
            updateBaseInfo(playerController.getPlayer());
            setPlayer(null);
        }
    }

    public Player getPlayer()
    {
        return playerController != null ? playerController.getPlayer() : player;
    }

    public Player getBasePlayer()
    {
        return player;
    }

    public RecoverParam getRecoverParam() {
        return recoverParam;
    }

    public void setRecoverParam(RecoverParam recoverParam) {
        this.recoverParam = recoverParam;
    }

    public PlayerController getPlayerController() {
        return playerController;
    }


    public List<Integer> getRouteList() {
        return routeList;
    }

    public E_ActionPlayerType getActionPlayerType() {
        return actionPlayerType;
    }

    public void setActionPlayerType(E_ActionPlayerType actionPlayerType, long outMapTime) {
        this.actionPlayerType = actionPlayerType;
        if (this.outMapTime == 0)
            this.outMapTime = outMapTime;
    }

    public SGCommonProto.E_ARMY_STATUS getStatus() {
        return status;
    }


    public int getCurRouteIndex() {
        return curRouteIndex;
    }

    public long getOutMapTime() {
        return outMapTime;
    }

    public void setOutMapTime(long outMapTime) {
        this.outMapTime = outMapTime;
    }

//    public Player getPlayer() {
//        return player;
//    }

    public void setPlayer(Player player)
    {
        this.player = player;
        if(player != null)
        {
            updateBaseInfo(player);
        }
    }

    public boolean isManualMatch() {
        return manualMatch;
    }

    public String getManualMatchPlayerIndex()
    {
        return manualMatchPlayerIndex;
    }

    public void setManualMatch(boolean manualMatch, String manualMatchPlayerIndex)
    {
        this.manualMatch = manualMatch;
        this.manualMatchPlayerIndex = manualMatchPlayerIndex;
    }

    @Override
    public String toString() {
        return "{" +
                "actionPlayerType=" + actionPlayerType +
                ", curRouteIndex=" + curRouteIndex +
                ", routeList=" + routeList +
                ", outMapTime=" + outMapTime +
                "}-" + super.toString();
    }
}
